Skip to content

fix(balances): consolidate Pioneer calls on /portfolio + fix USDT-TRON#47

Merged
BitHighlander merged 1 commit intodevelopfrom
fix/pioneer-portfolio-consolidation
Apr 24, 2026
Merged

fix(balances): consolidate Pioneer calls on /portfolio + fix USDT-TRON#47
BitHighlander merged 1 commit intodevelopfrom
fix/pioneer-portfolio-consolidation

Conversation

@BitHighlander
Copy link
Copy Markdown
Collaborator

Summary

Two related fixes that together make TRC-20 (USDT-TRON) appear on the dashboard for the first time, and bring the BEX's balance-fetch path in line with how the vault talks to Pioneer.

1. One endpoint instead of two

Before: pubkeys were split across two Pioneer endpoints:

  • `/api/v1/charts/portfolio` — for EVM, UTXO, Cosmos, TON, Tron (via a three-batch fan-out: `address`, `xpub`, `tron`)
  • `/api/v1/portfolio` — for Solana only

Plus a `/api/v1/{ton,tron}/accountInfo` fallback for partial responses.

`/charts/portfolio` serves natives from a pre-computed cache and decorates EVM tokens via Zapper — but does not run Pioneer's SPL / TRC-20 / Unchained ERC-20 auto-discovery blocks. Those live exclusively in `/api/v1/portfolio` (`GetPortfolioBalances`). That's why the vault — which uses `pioneer.GetPortfolioBalances` for everything — sees USDT-TRON and the BEX didn't.

After: one call, `/api/v1/portfolio`, all pubkeys (Solana + Tron + EVM + UTXO + Cosmos + TON + Ripple + THORChain). Native/token classification mirrors the vault's rule (`caip path not slip44:/native:` OR `type === 'token'` OR `isNative === false && contract`). Fallback is gone — vault doesn't have one either.

Net: −118 LOC. Slower per call (no pre-warm charts cache) — user explicitly accepted the latency trade to match vault exactly.

2. Tron has two network-ids; alias them

Pioneer emits the same Tron chain under two different IDs:

  • Native TRX → `tron:27Lqcw` (CAIP-2 genesis-hash convention)
  • TRC-20 tokens → `tron:0x2b6653dc` (hex chain-id convention)

Pioneer's canonical is `tron:0x2b6653dc` (that's what `pioneer-caip` / `pioneer-sdk` declare; vault consumes that and works). Our BEX has hardcoded `tron:27Lqcw` everywhere. Without a rewrite, the side-panel's strict `networkId === 'tron:27Lqcw'` filter skips every TRC-20 row.

Fix: alias at the response normalizer.

```ts
const NETWORK_ID_ALIASES = {
'tron:27lqcw': 'tron:27Lqcw', // casing
'tron:0x2b6653dc': 'tron:27Lqcw', // cross-convention
'solana:5eykt4...': 'solana:5eykt4UsFv8...' // existing Solana casing
};
```

Rewrites both `networkId` and the network prefix of `caip`. USDT-TRON now shows at the correct chain.

Known follow-up

The canonical-id mismatch is tech debt. Switching the BEX to `tron:0x2b6653dc` everywhere would drop the alias entry but requires a storage migration (existing users' pubkey caches have `networks: ['tron:27Lqcw']`). Deferred — alias is localized to one function and cheap to maintain.

Test plan

  • Build clean
  • Live-queried Pioneer to confirm endpoint behavior before consolidating
  • Verified native TRX + USDT-TRON both appear on the Tron asset page after reload
  • EVM send still works (ERC-20s still populate)
  • UTXO chains still populate (BTC xpubs + altcoins)
  • Cosmos / THORChain / Ripple natives still populate
  • Solana + SPL tokens still populate
  • TON native still populates (no more gap-patch fallback — relying on /portfolio)

🤖 Generated with Claude Code

…etwork-ids

Two related fixes that together make TRC-20 (USDT-TRON) appear on the
dashboard for the first time.

1. One endpoint instead of two
---------------------------------
Before: the Pioneer call was split across /charts/portfolio (for
EVM/UTXO/Cosmos/TON) and /portfolio (for Solana only), with a separate
fallback for TON/TRON partial responses. /charts/portfolio is a fast
cached path backed by pre-computed charts + Zapper-provided EVM
tokens; it does NOT run Pioneer's SPL / TRC-20 / ERC-20 auto-discovery
blocks that live in balance.controller.ts. Only /portfolio
(GetPortfolioBalances) hits those — which is why the vault, which uses
/portfolio exclusively via pioneer-client, saw USDT while the BEX did
not.

Consolidated every pubkey (Solana + Tron + EVM + UTXO + Cosmos + TON
+ Ripple + THORChain) onto /portfolio in one call, matching vault's
GetPortfolioBalances flow exactly. Classification (native vs token)
uses the same rule as vault: caip path not in {slip44:, native:}
OR type === 'token' OR (isNative === false && contract).

Net: -118 lines vs. the three-batch split. Slower per call (no
pre-warm charts cache) but correct, and the user explicitly accepted
the latency trade.

2. Tron has two network-ids; alias them
------------------------------------------
Pioneer emits the native TRX balance under `tron:27Lqcw` (CAIP-2
genesis-hash convention), but TRC-20 tokens under `tron:0x2b6653dc`
(hex chain-id convention). Both refer to Tron mainnet. Pioneer's own
ChainToNetworkId declares `tron:0x2b6653dc` as canonical (vault
consumes that and works); our BEX has hardcoded `tron:27Lqcw`
throughout `chainConfig.ts` and `tronHandler.ts`. Rather than rewire
every pubkey cache entry in users' storage, alias Pioneer's response
ids at the normalizer:

  NETWORK_ID_ALIASES = {
    'tron:27lqcw'      -> 'tron:27Lqcw'          // casing
    'tron:0x2b6653dc'  -> 'tron:27Lqcw'          // cross-convention
    'solana:5eykt4...' -> 'solana:5eykt4UsFv8...' // existing Solana casing
  }

Rewrites both `networkId` and the network prefix of `caip`. The
side-panel's strict `networkId === 'tron:27Lqcw'` filter now matches
both native rows and TRC-20 token rows, so USDT-TRON appears on the
Tron asset page.

Known ceiling: the canonical-id mismatch is tech debt. Switching our
BEX to `tron:0x2b6653dc` would remove the alias entry but requires a
storage migration (existing pubkey caches have `networks:
['tron:27Lqcw']`). Deferred — alias is localized and cheap.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@BitHighlander BitHighlander merged commit 03533bb into develop Apr 24, 2026
4 of 5 checks passed
@BitHighlander BitHighlander deleted the fix/pioneer-portfolio-consolidation branch April 24, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant